import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.platform.Font
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.InetAddress
import java.net.ServerSocket
import java.net.Socket
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.thread

class ChatServer(private val port: Int = 9999) {
    private val clients = mutableListOf<ClientHandler>()
    private var serverSocket: ServerSocket? = null
    private var isRunning = false
    private val dateFormat = SimpleDateFormat("HH:mm:ss")

    private val users = mapOf(
        "admin" to "admin123",
        "阿伟" to "123456",
        "大橙子" to "123456",
        "哥哥" to "123456",
        "大伟" to "alice123",
        "bob" to "bob123",
        "charlie" to "charlie123",
        "david" to "david123"
    )

    var logMessages by mutableStateOf("")

    fun log(message: String) {
        logMessages += "[${dateFormat.format(Date())}] $message\n"
    }

    fun getLocalIpAddress(): String {
        return try {
            InetAddress.getLocalHost().hostAddress
        } catch (e: Exception) {
            "Unknown"
        }
    }

    fun start() {
        try {
            serverSocket = ServerSocket(port)
            isRunning = true
            log("服务器启动在端口: $port")

            while (isRunning) {
                try {
                    val clientSocket = serverSocket?.accept()
                    clientSocket?.let {
                        val handler = ClientHandler(it)
                        clients.add(handler)
                        log("新客户端连接: ${it.inetAddress.hostAddress}")
                        thread { handler.handle() }
                    }
                } catch (e: Exception) {
                    if (isRunning) {
                        log("接受客户端连接时出错: ${e.message}")
                    }
                }
            }
        } catch (e: Exception) {
            log("服务器启动失败: ${e.message}")
        }
    }

    inner class ClientHandler(internal val socket: Socket) {
        private val reader = BufferedReader(InputStreamReader(socket.getInputStream()))
        private val writer = PrintWriter(socket.getOutputStream(), true)
        internal val clientAddress = socket.inetAddress.hostAddress
        internal var username: String? = null

        fun handle() {
            try {
                while (isRunning && !socket.isClosed) {
                    val message = reader.readLine()
                    if (message == null) {
                        log("客户端连接已关闭")
                        break
                    }

                    if (message == "HEARTBEAT") {
                        writer.println("HEARTBEAT")
                        writer.flush()
                        continue
                    }

                    if (username == null) {
                        if (message.startsWith("LOGIN:")) {
                            handleLogin(message)
                        }
                    } else {
                        log("收到来自 $username 的消息: $message")
                        synchronized(clients) {
                            broadcast("$username: $message", this)
                        }
                    }
                }
            } catch (e: Exception) {
                log("客户端 ${username ?: clientAddress} 异常断开: ${e.message}")
            } finally {
                disconnect()
            }
        }

        private fun handleLogin(message: String) {
            val parts = message.split(":")
            if (parts.size == 3) {
                val username = parts[1]
                val password = parts[2]

                log("收到登录请求: username=$username")

                synchronized(clients) {
                    val existingClient = clients.find { it.username == username }
                    if (existingClient != null) {
                        log("用户 $username 已在其他设备登录")
                        writer.println("LOGIN_FAILED:ALREADY_LOGGED_IN")
                        writer.flush()
                        return
                    }
                }

                if (users[username] == password) {
                    this.username = username
                    log("密码验证成功，发送 LOGIN_SUCCESS")
                    val response = "LOGIN_SUCCESS:$username"
                    writer.println(response)
                    writer.flush()
                    log("已发送登录成功响应: $response")

                    synchronized(clients) {
                        broadcast("SYSTEM:$username 加入了聊天室", null)
                    }
                } else {
                    log("密码验证失败，发送 LOGIN_FAILED")
                    writer.println("LOGIN_FAILED")
                    writer.flush()
                    log("已发送登录失败响应")
                }
            } else {
                log("登录消息格式错误: $message")
                writer.println("LOGIN_FAILED")
                writer.flush()
                log("已发送登录失败响应")
            }
        }

        private fun disconnect() {
            synchronized(clients) {
                if (clients.remove(this) && username != null) {
                    broadcast("SYSTEM:$username 离开了聊天室", null)
                }
            }
            try {
                socket.close()
                log("客户端 ${username ?: clientAddress} 断开连接")
            } catch (e: Exception) {
                log("关闭客户端连接时出错: ${e.message}")
            }
        }

        fun send(message: String) {
            try {
                if (!socket.isClosed) {
                    writer.println(message)
                    writer.flush()
                    log("消息发送成功: $message")
                }
            } catch (e: Exception) {
                log("发送消息到客户端 ${username ?: clientAddress} 失败: ${e.message}")
                disconnect()
            }
        }
    }

    private fun broadcast(message: String, sender: ClientHandler? = null) {
        synchronized(clients) {
            val activeClients = clients.filter { !it.socket.isClosed }
            activeClients.forEach { client ->
                if (client != sender) {
                    try {
                        client.send(message)
                        log("广播消息到 ${client.username ?: client.clientAddress}: $message")
                    } catch (e: Exception) {
                        log("广播消息失败: ${e.message}")
                    }
                }
            }
            clients.removeAll { it.socket.isClosed }
        }
    }

    fun stop() {
        isRunning = false
        clients.toList().forEach { client ->
            try {
                client.socket.close()
            } catch (e: Exception) {
                log("关闭客户端连接时出错: ${e.message}")
            }
        }
        clients.clear()
        try {
            serverSocket?.close()
            log("服务器已停止")
        } catch (e: Exception) {
            log("停止服务器时出错: ${e.message}")
        }
    }
}

private val sourceHanSerif = FontFamily(
    Font(
        resource = "fonts/SourceHanSerifCN-Regular.otf",
        weight = FontWeight.Normal
    ),
    Font(
        resource = "fonts/SourceHanSerifCN-Bold.otf",
        weight = FontWeight.Bold,
    )
)

private val customTypography = Typography(
    defaultFontFamily = sourceHanSerif,
    h6 = TextStyle(
        fontFamily = sourceHanSerif,
        fontWeight = FontWeight.Normal,
        fontSize = 20.sp
    ),
    body1 = TextStyle(
        fontFamily = sourceHanSerif,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp
    ),
    body2 = TextStyle(
        fontFamily = sourceHanSerif,
        fontWeight = FontWeight.Normal,
        fontSize = 14.sp
    )
)

@Composable
fun ChatServerUI(chatServer: ChatServer) {
    var isRunning by remember { mutableStateOf(false) }
    val serverIpAddress = chatServer.getLocalIpAddress()
    val logMessages = chatServer.logMessages.split("\n").filter { it.isNotEmpty() }
    val listState = rememberLazyListState()

    LaunchedEffect(logMessages.size) {
        if (logMessages.isNotEmpty()) {
            listState.animateScrollToItem(logMessages.size - 1)
        }
    }

    MaterialTheme(
        typography = customTypography
    ) {
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = Color(0xFFF2F2F2)
        ) {
            Column(
                modifier = Modifier.fillMaxSize().padding(16.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp)
            ) {
                // 第一个卡片：服务器IP信息
                Card(
                    modifier = Modifier.fillMaxWidth(),
                    elevation = 4.dp
                ) {
                    Row(
                        modifier = Modifier.padding(16.dp),
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Text(
                            "服务器 IP：",
                            style = MaterialTheme.typography.body1.copy(
                                fontWeight = FontWeight.Bold
                            )
                        )
                        Text(
                            serverIpAddress,
                            style = MaterialTheme.typography.body1
                        )
                    }
                }

                // 第二个卡片：服务器控制
                Card(
                    modifier = Modifier.fillMaxWidth(),
                    elevation = 4.dp
                ) {
                    Row(
                        modifier = Modifier.padding(16.dp),
                        horizontalArrangement = Arrangement.SpaceBetween,
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Text(
                            "服务器控制",
                            style = MaterialTheme.typography.body1.copy(
                                fontWeight = FontWeight.Bold
                            ),
                            modifier = Modifier.weight(1f)
                        )
                        Row(
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Button(
                                onClick = {
                                    isRunning = true
                                    thread { chatServer.start() }
                                },
                                enabled = !isRunning,
                                colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFFFF784B))
                            ) {
                                Text("启动服务器", color = Color.White)
                            }
                            Button(
                                onClick = {
                                    isRunning = false
                                    chatServer.stop()
                                },
                                enabled = isRunning,
                                colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFFFF784B))
                            ) {
                                Text("停止服务器", color = Color.White)
                            }
                        }
                    }
                }

                // 第三个卡片：日志信息
                Card(
                    modifier = Modifier.weight(1f).fillMaxWidth(),
                    elevation = 4.dp
                ) {
                    Column(
                        modifier = Modifier.padding(16.dp)
                    ) {
                        Text(
                            "日志信息",
                            style = MaterialTheme.typography.body1.copy(
                                fontWeight = FontWeight.Bold
                            ),
                            modifier = Modifier.padding(bottom = 16.dp)
                        )
                        Box(
                            modifier = Modifier.weight(1f).fillMaxWidth()
                        ) {
                            LazyColumn(
                                modifier = Modifier.fillMaxSize(),
                                state = listState,
                                verticalArrangement = Arrangement.spacedBy(8.dp)
                            ) {
                                items(logMessages.size) { index ->
                                    LogMessageCard(logMessages[index])
                                }
                            }
                            VerticalScrollbar(
                                adapter = rememberScrollbarAdapter(listState),
                                modifier = Modifier.align(Alignment.CenterEnd)
                            )
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun LogMessageCard(logMessage: String) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 3.dp)
            .background(
                color = MaterialTheme.colors.surface.copy(alpha = 0.7f),
                shape = MaterialTheme.shapes.small
            )
            .padding(4.dp)
    ) {
        Text(
            text = logMessage,
            style = MaterialTheme.typography.body2.copy(fontWeight = FontWeight.Medium)
        )
    }
}




fun main() = application {
    val chatServer = ChatServer()
    Window(
        onCloseRequest = ::exitApplication,
        title = "聊天服务器",
        icon = painterResource("icon.png")
    ) {
        ChatServerUI(chatServer)
    }
}


